package qc.module.qms.service.pointdata;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import qc.common.core.enums.qms.QmsPointDataQualityEnum;
import qc.common.core.enums.qms.QmsPointValueFieldEnum;
import qc.common.core.exception.QCPromptException;
import qc.common.core.unify.QCUnifyReturnValue;
import qc.common.core.utils.LocalDateTimeUtil;
import qc.module.qms.entity.QmsPointWeekNumericData;
import qc.module.qms.repository.QmsPointWeekNumericDataRepository;

import java.time.LocalDateTime;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * QmsPointWeekNumericDataService
 *
 * @author QuCheng Tech
 * @since 2025/9/25
 */
@Service
public class QmsPointWeekNumericDataService {
    private static final Logger logger = LoggerFactory.getLogger(QmsPointWeekNumericDataService.class);

    @Autowired
    private QmsPointWeekNumericDataRepository repository;

    /**
     * 查询指定时间段数据，每条数据均包含全部信息（值、时段初末值、最值及时间、数据质量）
     *
     * @param pointid          点号
     * @param beginTime        起始时间
     * @param endTime          截止时间
     * @param excludeBeginTime 不包含起始时间点
     * @param excludeEndTime   不包含截止时间点
     * @param quality          质量标记，传入未定义是表示全部数据，传入其他表示≥该质量的数据
     * @return java.util.List<qc.module.qms.entity.QmsPointWeekNumericData>
     * @author QuCheng Tech
     * @since 2025/9/25
     */
    public List<QmsPointWeekNumericData> query(String pointid, LocalDateTime beginTime, LocalDateTime endTime,
                                               boolean excludeBeginTime, boolean excludeEndTime, QmsPointDataQualityEnum quality) {
        logger.debug("query 查询周点号时间段内数据，点号[" + pointid + "]，起始时间[" + LocalDateTimeUtil.formatDateTime(beginTime) + "]，截止时间[" + LocalDateTimeUtil.formatDateTime(endTime)
                + "]，不包含起始时间点[" + excludeBeginTime + "]，不包含截止时间点[" + excludeEndTime + "]，数据质量≥[" + quality.toString() + "]");

        //点号不能为空，起始时间不能为空并且正确
        if (StringUtils.isNotBlank(pointid) && beginTime != null && endTime != null && endTime.isBefore(beginTime) == false) {
            //需要根据时段类型指定不同的实体类
            LambdaQueryWrapper<QmsPointWeekNumericData> wrapper = new LambdaQueryWrapper<>();
            //查询条件
            //点号相等
            wrapper.eq(QmsPointWeekNumericData::getPointid, pointid);
            //判断起始时间
            if (excludeBeginTime == false)//包含起始时间点
                wrapper.ge(QmsPointWeekNumericData::getTm, beginTime);
            else//不包含起始时间点
                wrapper.gt(QmsPointWeekNumericData::getTm, beginTime);
            //判断截止时间
            if (excludeEndTime == false)//包含起始时间点
                wrapper.le(QmsPointWeekNumericData::getTm, endTime);
            else//不包含起始时间点
                wrapper.lt(QmsPointWeekNumericData::getTm, endTime);
            //判断数据质量要求
            if (quality != QmsPointDataQualityEnum.UN_DEFINE)
                wrapper.ge(QmsPointWeekNumericData::getQuality, quality);

            //排序，按时间Asc
            wrapper.orderByAsc(QmsPointWeekNumericData::getTm);

            //查询数据
            return repository.selectList(wrapper);
        }

        return null;
    }

    /**
     * 查询指定时间段指定数值字段的数据，只包含数据时间和对应数值字段的值
     *
     * @param pointid          点号
     * @param valueField       数值字段，指定错误或无效默认为value字段；要求指定的字段值不能为null
     * @param beginTime        起始时间
     * @param endTime          截止时间
     * @param excludeBeginTime 不包含起始时间点
     * @param excludeEndTime   不包含截止时间点
     * @param quality          质量标记，传入未定义是表示全部数据，传入其他表示≥该质量的数据
     * @return java.util.List<qc.module.qms.dto.pointdata.QmsPointNumericDataDto>
     * @author QuCheng Tech
     * @since 2025/9/25
     */
    public Map<LocalDateTime, Double> queryFieldValues(String pointid, QmsPointValueFieldEnum valueField, LocalDateTime beginTime, LocalDateTime endTime,
                                                       boolean excludeBeginTime, boolean excludeEndTime, QmsPointDataQualityEnum quality) {
        logger.debug("queryFieldValues 查询周点号时间段内指定数据值，点号[" + pointid + "]，数值字段[" + valueField.toString()
                + "]，起始时间[" + LocalDateTimeUtil.formatDateTime(beginTime) + "]，截止时间[" + LocalDateTimeUtil.formatDateTime(endTime)
                + "]，不包含起始时间点[" + excludeBeginTime + "]，不包含截止时间点[" + excludeEndTime + "]，数据质量≥[" + quality.toString() + "]");

        //点号不能为空，起始时间不能为空并且正确
        if (StringUtils.isNotBlank(pointid) && beginTime != null && endTime != null && endTime.isBefore(beginTime) == false) {
            //需要根据时段类型指定不同的实体类
            LambdaQueryWrapper<QmsPointWeekNumericData> wrapper = new LambdaQueryWrapper<>();
            //指定查询的列，只要tm和数据值字段列，共2列的数据
            if (valueField == QmsPointValueFieldEnum.BEGIN_VALUE)//时段初值
                wrapper.select(QmsPointWeekNumericData::getTm, QmsPointWeekNumericData::getBeginv);
            else if (valueField == QmsPointValueFieldEnum.END_VALUE)//时段末值
                wrapper.select(QmsPointWeekNumericData::getTm, QmsPointWeekNumericData::getEndv);
            else if (valueField == QmsPointValueFieldEnum.MAX_VALUE)//最大值
                wrapper.select(QmsPointWeekNumericData::getTm, QmsPointWeekNumericData::getMaxv);
            else if (valueField == QmsPointValueFieldEnum.MIN_VALUE)//最小值
                wrapper.select(QmsPointWeekNumericData::getTm, QmsPointWeekNumericData::getMinv);
            else//其他均查询value字段的值
                wrapper.select(QmsPointWeekNumericData::getTm, QmsPointWeekNumericData::getV);

            //查询条件
            //点号相等
            wrapper.eq(QmsPointWeekNumericData::getPointid, pointid);
            //判断起始时间
            if (excludeBeginTime == false)//包含起始时间点
                wrapper.ge(QmsPointWeekNumericData::getTm, beginTime);
            else//不包含起始时间点
                wrapper.gt(QmsPointWeekNumericData::getTm, beginTime);
            //判断截止时间
            if (excludeEndTime == false)//包含起始时间点
                wrapper.le(QmsPointWeekNumericData::getTm, endTime);
            else//不包含起始时间点
                wrapper.lt(QmsPointWeekNumericData::getTm, endTime);
            //判断数据质量要求
            if (quality != QmsPointDataQualityEnum.UN_DEFINE)
                wrapper.ge(QmsPointWeekNumericData::getQuality, quality);
            //将查询指定字段数据值为null的排除在外
            if (valueField == QmsPointValueFieldEnum.BEGIN_VALUE)//时段初值
                wrapper.isNotNull(QmsPointWeekNumericData::getBeginv);
            else if (valueField == QmsPointValueFieldEnum.END_VALUE)//时段末值
                wrapper.isNotNull(QmsPointWeekNumericData::getEndv);
            else if (valueField == QmsPointValueFieldEnum.MAX_VALUE)//最大值
                wrapper.isNotNull(QmsPointWeekNumericData::getMaxv);
            else if (valueField == QmsPointValueFieldEnum.MIN_VALUE)//最小值
                wrapper.isNotNull(QmsPointWeekNumericData::getMinv);
            else//其他均查询value字段的值
                wrapper.isNotNull(QmsPointWeekNumericData::getV);

            //排序，按时间Asc
            wrapper.orderByAsc(QmsPointWeekNumericData::getTm);

            //查询数据
            List<QmsPointWeekNumericData> ens = repository.selectList(wrapper);
            if (ens != null && ens.size() > 0x0) {
                //按时间顺序返回
                Map<LocalDateTime, Double> result = new LinkedHashMap<>();

                for (QmsPointWeekNumericData en : ens) {
                    if (valueField == QmsPointValueFieldEnum.BEGIN_VALUE)//时段初值
                        result.put(en.getTm(), en.getBeginv());
                    else if (valueField == QmsPointValueFieldEnum.END_VALUE)//时段末值
                        result.put(en.getTm(), en.getEndv());
                    else if (valueField == QmsPointValueFieldEnum.MAX_VALUE)//最大值
                        result.put(en.getTm(), en.getMaxv());
                    else if (valueField == QmsPointValueFieldEnum.MIN_VALUE)//最小值
                        result.put(en.getTm(), en.getMinv());
                    else//其他均查询value字段的值
                        result.put(en.getTm(), en.getV());
                }

                return result;
            }
        }

        return null;
    }

    /**
     * 获取指定时间点的数据，仅查询指定的时间点，不往前或往后查询数据
     *
     * @param pointid 点号
     * @param time    时间点
     * @param quality 质量标记，传入未定义是表示全部数据，传入其他表示≥该质量的数据
     * @return qc.module.qms.entity.QmsPointWeekNumericData
     * @author QuCheng Tech
     * @since 2025/9/25
     */
    public QmsPointWeekNumericData get(String pointid, LocalDateTime time, QmsPointDataQualityEnum quality) {
        logger.debug("get 获取指定时间点周点号数据，点号[" + pointid + "]，时间[" + LocalDateTimeUtil.formatDateTime(time) + "]，数据质量≥[" + quality.toString() + "]");

        //点号不能为空，时间点不能为空
        if (StringUtils.isNotBlank(pointid) && time != null) {
            LambdaQueryWrapper<QmsPointWeekNumericData> wrapper = new LambdaQueryWrapper<>();
            //查询条件
            //点号相等
            wrapper.eq(QmsPointWeekNumericData::getPointid, pointid);
            //判断时间相等
            wrapper.eq(QmsPointWeekNumericData::getTm, time);
            //判断数据质量要求
            if (quality != QmsPointDataQualityEnum.UN_DEFINE)
                wrapper.ge(QmsPointWeekNumericData::getQuality, quality);

            //不需要排序，指定时间点应该只有一条数据

            //查询数据
            return repository.selectOne(wrapper);
        }

        return null;
    }

    /**
     * 获取指定时间点的指定数值字段的数据，只包含数据时间和对应数值字段的值；仅查询指定的时间点，不往前或往后查询数据
     *
     * @param pointid    点号
     * @param valueField 数值字段，指定错误或无效默认为value字段；要求指定的字段值不能为null
     * @param time       时间点
     * @param quality    质量标记，传入未定义是表示全部数据，传入其他表示≥该质量的数据
     * @return java.util.Map<java.time.LocalDateTime, java.lang.Double>
     * @author QuCheng Tech
     * @since 2025/9/25
     */
    public Map<LocalDateTime, Double> getFieldValue(String pointid, QmsPointValueFieldEnum valueField, LocalDateTime time, QmsPointDataQualityEnum quality) {
        logger.debug("getFieldValue 获取指定时间点周点号指定数据值，点号[" + pointid + "]，数值字段[" + valueField.toString() + "]，时间[" + LocalDateTimeUtil.formatDateTime(time) + "]，数据质量≥[" + quality.toString() + "]");

        //点号不能为空，时间点不能为空
        if (StringUtils.isNotBlank(pointid) && time != null) {
            LambdaQueryWrapper<QmsPointWeekNumericData> wrapper = new LambdaQueryWrapper<>();
            //指定查询的列，只要tm和数据值字段列，共2列的数据
            if (valueField == QmsPointValueFieldEnum.BEGIN_VALUE)//时段初值
                wrapper.select(QmsPointWeekNumericData::getTm, QmsPointWeekNumericData::getBeginv);
            else if (valueField == QmsPointValueFieldEnum.END_VALUE)//时段末值
                wrapper.select(QmsPointWeekNumericData::getTm, QmsPointWeekNumericData::getEndv);
            else if (valueField == QmsPointValueFieldEnum.MAX_VALUE)//最大值
                wrapper.select(QmsPointWeekNumericData::getTm, QmsPointWeekNumericData::getMaxv);
            else if (valueField == QmsPointValueFieldEnum.MIN_VALUE)//最小值
                wrapper.select(QmsPointWeekNumericData::getTm, QmsPointWeekNumericData::getMinv);
            else//其他均查询value字段的值
                wrapper.select(QmsPointWeekNumericData::getTm, QmsPointWeekNumericData::getV);

            //查询条件
            //点号相等
            wrapper.eq(QmsPointWeekNumericData::getPointid, pointid);
            //判断时间相等
            wrapper.eq(QmsPointWeekNumericData::getTm, time);
            //判断数据质量要求
            if (quality != QmsPointDataQualityEnum.UN_DEFINE)
                wrapper.ge(QmsPointWeekNumericData::getQuality, quality);
            //将查询指定字段数据值为null的排除在外
            if (valueField == QmsPointValueFieldEnum.BEGIN_VALUE)//时段初值
                wrapper.isNotNull(QmsPointWeekNumericData::getBeginv);
            else if (valueField == QmsPointValueFieldEnum.END_VALUE)//时段末值
                wrapper.isNotNull(QmsPointWeekNumericData::getEndv);
            else if (valueField == QmsPointValueFieldEnum.MAX_VALUE)//最大值
                wrapper.isNotNull(QmsPointWeekNumericData::getMaxv);
            else if (valueField == QmsPointValueFieldEnum.MIN_VALUE)//最小值
                wrapper.isNotNull(QmsPointWeekNumericData::getMinv);
            else//其他均查询value字段的值
                wrapper.isNotNull(QmsPointWeekNumericData::getV);

            //不需要排序，指定时间点应该只有一条数据

            //查询数据
            QmsPointWeekNumericData en = repository.selectOne(wrapper);
            if (en != null) {
                Map<LocalDateTime, Double> result = new LinkedHashMap<>();

                if (valueField == QmsPointValueFieldEnum.BEGIN_VALUE)//时段初值
                    result.put(en.getTm(), en.getBeginv());
                else if (valueField == QmsPointValueFieldEnum.END_VALUE)//时段末值
                    result.put(en.getTm(), en.getEndv());
                else if (valueField == QmsPointValueFieldEnum.MAX_VALUE)//最大值
                    result.put(en.getTm(), en.getMaxv());
                else if (valueField == QmsPointValueFieldEnum.MIN_VALUE)//最小值
                    result.put(en.getTm(), en.getMinv());
                else//其他均查询value字段的值
                    result.put(en.getTm(), en.getV());

                return result;
            }
        }

        return null;
    }

    /**
     * 获取不大于指定时间点最新一条数据
     *
     * @param pointid 点号
     * @param time    时间点
     * @param quality 质量标记，传入未定义是表示全部数据，传入其他表示≥该质量的数据
     * @return qc.module.qms.entity.QmsPointWeekNumericData
     * @author QuCheng Tech
     * @since 2025/9/25
     */
    public QmsPointWeekNumericData getNoMoreThan(String pointid, LocalDateTime time, QmsPointDataQualityEnum quality) {
        return getNoMoreThan(pointid, time, quality, false);
    }

    /**
     * 获取不大于指定时间点最新一条数据
     *
     * @param pointid 点号
     * @param time    时间点
     * @param quality 质量标记，传入未定义是表示全部数据，传入其他表示≥该质量的数据
     * @return qc.module.qms.entity.QmsPointWeekNumericData
     * @author QuCheng Tech
     * @since 2025/9/25
     */
    public QmsPointWeekNumericData getNoMoreThan(String pointid, LocalDateTime time, QmsPointDataQualityEnum quality, boolean notEqualTime) {
        logger.debug("getNoMoreThan 获取不大于指定时间点周点号数据，点号[" + pointid + "]，时间" + (notEqualTime ? "＜" : "≤") + "[" + LocalDateTimeUtil.formatDateTime(time) + "]，数据质量≥[" + quality.toString() + "]");

        //点号不能为空，时间点不能为空
        if (StringUtils.isNotBlank(pointid) && time != null) {
            LambdaQueryWrapper<QmsPointWeekNumericData> wrapper = new LambdaQueryWrapper<>();
            //查询条件
            //点号相等
            wrapper.eq(QmsPointWeekNumericData::getPointid, pointid);
            //判断时间,不大于指定时间点，≤time
            if (notEqualTime == false)
                wrapper.le(QmsPointWeekNumericData::getTm, time);
            else
                wrapper.lt(QmsPointWeekNumericData::getTm, time);
            //判断数据质量要求
            if (quality != QmsPointDataQualityEnum.UN_DEFINE)
                wrapper.ge(QmsPointWeekNumericData::getQuality, quality);

            //按时间Desc，限制1条
            wrapper.orderByDesc(QmsPointWeekNumericData::getTm);
            wrapper.last("limit 1");

            //查询数据
            return repository.selectOne(wrapper);
        }

        return null;
    }

    /**
     * 获取不大于指定时间点最新一条指定数值字段的数据，只包含数据时间和对应数值字段的值
     *
     * @param pointid    点号
     * @param valueField 数值字段，指定错误或无效默认为value字段；要求指定的字段值不能为null
     * @param time       时间点
     * @param quality    质量标记，传入未定义是表示全部数据，传入其他表示≥该质量的数据
     * @return java.util.Map<java.time.LocalDateTime, java.lang.Double>
     * @author QuCheng Tech
     * @since 2025/9/25
     */
    public Map<LocalDateTime, Double> getNoMoreThanFieldValue(String pointid, QmsPointValueFieldEnum valueField, LocalDateTime time, QmsPointDataQualityEnum quality) {
        logger.debug("getNoMoreThanFieldValue 获取不大于指定时间点周点号指定数据值，点号[" + pointid + "]，数值字段[" + valueField.toString() + "]，时间[" + LocalDateTimeUtil.formatDateTime(time) + "]，数据质量≥[" + quality.toString() + "]");

        //点号不能为空，时间点不能为空
        if (StringUtils.isNotBlank(pointid) && time != null) {
            LambdaQueryWrapper<QmsPointWeekNumericData> wrapper = new LambdaQueryWrapper<>();
            //指定查询的列，只要tm和数据值字段列，共2列的数据
            if (valueField == QmsPointValueFieldEnum.BEGIN_VALUE)//时段初值
                wrapper.select(QmsPointWeekNumericData::getTm, QmsPointWeekNumericData::getBeginv);
            else if (valueField == QmsPointValueFieldEnum.END_VALUE)//时段末值
                wrapper.select(QmsPointWeekNumericData::getTm, QmsPointWeekNumericData::getEndv);
            else if (valueField == QmsPointValueFieldEnum.MAX_VALUE)//最大值
                wrapper.select(QmsPointWeekNumericData::getTm, QmsPointWeekNumericData::getMaxv);
            else if (valueField == QmsPointValueFieldEnum.MIN_VALUE)//最小值
                wrapper.select(QmsPointWeekNumericData::getTm, QmsPointWeekNumericData::getMinv);
            else//其他均查询value字段的值
                wrapper.select(QmsPointWeekNumericData::getTm, QmsPointWeekNumericData::getV);

            //查询条件
            //点号相等
            wrapper.eq(QmsPointWeekNumericData::getPointid, pointid);
            //判断时间,不大于指定时间点，≤time
            wrapper.le(QmsPointWeekNumericData::getTm, time);
            //判断数据质量要求
            if (quality != QmsPointDataQualityEnum.UN_DEFINE)
                wrapper.ge(QmsPointWeekNumericData::getQuality, quality);
            //将查询指定字段数据值为null的排除在外
            if (valueField == QmsPointValueFieldEnum.BEGIN_VALUE)//时段初值
                wrapper.isNotNull(QmsPointWeekNumericData::getBeginv);
            else if (valueField == QmsPointValueFieldEnum.END_VALUE)//时段末值
                wrapper.isNotNull(QmsPointWeekNumericData::getEndv);
            else if (valueField == QmsPointValueFieldEnum.MAX_VALUE)//最大值
                wrapper.isNotNull(QmsPointWeekNumericData::getMaxv);
            else if (valueField == QmsPointValueFieldEnum.MIN_VALUE)//最小值
                wrapper.isNotNull(QmsPointWeekNumericData::getMinv);
            else//其他均查询value字段的值
                wrapper.isNotNull(QmsPointWeekNumericData::getV);

            //按时间Desc，限制1条
            wrapper.orderByDesc(QmsPointWeekNumericData::getTm);
            wrapper.last("limit 1");

            //查询数据
            QmsPointWeekNumericData en = repository.selectOne(wrapper);
            if (en != null) {
                Map<LocalDateTime, Double> result = new LinkedHashMap<>();

                if (valueField == QmsPointValueFieldEnum.BEGIN_VALUE)//时段初值
                    result.put(en.getTm(), en.getBeginv());
                else if (valueField == QmsPointValueFieldEnum.END_VALUE)//时段末值
                    result.put(en.getTm(), en.getEndv());
                else if (valueField == QmsPointValueFieldEnum.MAX_VALUE)//最大值
                    result.put(en.getTm(), en.getMaxv());
                else if (valueField == QmsPointValueFieldEnum.MIN_VALUE)//最小值
                    result.put(en.getTm(), en.getMinv());
                else//其他均查询value字段的值
                    result.put(en.getTm(), en.getV());

                return result;
            }
        }

        return null;
    }

    /**
     * 获取不小于指定时间点最新一条数据
     *
     * @param pointid 点号
     * @param time    时间点
     * @param quality 质量标记，传入未定义是表示全部数据，传入其他表示≥该质量的数据
     * @return qc.module.qms.entity.QmsPointWeekNumericData
     * @author QuCheng Tech
     * @since 2025/9/25
     */
    public QmsPointWeekNumericData getNoLessThan(String pointid, LocalDateTime time, QmsPointDataQualityEnum quality) {
        return getNoLessThan(pointid, time, quality, false);
    }

    /**
     * 获取不小于指定时间点最新一条数据
     *
     * @param pointid 点号
     * @param time    时间点
     * @param quality 质量标记，传入未定义是表示全部数据，传入其他表示≥该质量的数据
     * @return qc.module.qms.entity.QmsPointWeekNumericData
     * @author QuCheng Tech
     * @since 2025/9/25
     */
    public QmsPointWeekNumericData getNoLessThan(String pointid, LocalDateTime time, QmsPointDataQualityEnum quality, boolean notEqualTime) {
        logger.debug("getNoMoreThan 获取不小于指定时间点周点号数据，点号[" + pointid + "]，时间" + (notEqualTime ? "＞" : "≥") + "[" + LocalDateTimeUtil.formatDateTime(time) + "]，数据质量≥[" + quality.toString() + "]");

        //点号不能为空，时间点不能为空
        if (StringUtils.isNotBlank(pointid) && time != null) {
            LambdaQueryWrapper<QmsPointWeekNumericData> wrapper = new LambdaQueryWrapper<>();
            //查询条件
            //点号相等
            wrapper.eq(QmsPointWeekNumericData::getPointid, pointid);
            //判断时间,不小于指定时间点，≥time
            if (notEqualTime == false)
                wrapper.ge(QmsPointWeekNumericData::getTm, time);
            else
                wrapper.gt(QmsPointWeekNumericData::getTm, time);
            //判断数据质量要求
            if (quality != QmsPointDataQualityEnum.UN_DEFINE)
                wrapper.ge(QmsPointWeekNumericData::getQuality, quality);

            //按时间Asc，限制1条
            wrapper.orderByAsc(QmsPointWeekNumericData::getTm);
            wrapper.last("limit 1");

            //查询数据
            return repository.selectOne(wrapper);
        }

        return null;
    }

    /**
     * 获取不小于指定时间点最新一条指定数值字段的数据，只包含数据时间和对应数值字段的值
     *
     * @param pointid    点号
     * @param valueField 数值字段，指定错误或无效默认为value字段；要求指定的字段值不能为null
     * @param time       时间点
     * @param quality    质量标记，传入未定义是表示全部数据，传入其他表示≥该质量的数据
     * @return java.util.Map<java.time.LocalDateTime, java.lang.Double>
     * @author QuCheng Tech
     * @since 2025/9/25
     */
    public Map<LocalDateTime, Double> getNoLessThanFieldValue(String pointid, QmsPointValueFieldEnum valueField, LocalDateTime time, QmsPointDataQualityEnum quality) {
        logger.debug("getNoLessThanFieldValue 获取不小于指定时间点周点号指定数据值，点号[" + pointid + "]，数值字段[" + valueField.toString() + "]，时间[" + LocalDateTimeUtil.formatDateTime(time) + "]，数据质量≥[" + quality.toString() + "]");

        //点号不能为空，时间点不能为空
        if (StringUtils.isNotBlank(pointid) && time != null) {
            LambdaQueryWrapper<QmsPointWeekNumericData> wrapper = new LambdaQueryWrapper<>();
            //指定查询的列，只要tm和数据值字段列，共2列的数据
            if (valueField == QmsPointValueFieldEnum.BEGIN_VALUE)//时段初值
                wrapper.select(QmsPointWeekNumericData::getTm, QmsPointWeekNumericData::getBeginv);
            else if (valueField == QmsPointValueFieldEnum.END_VALUE)//时段末值
                wrapper.select(QmsPointWeekNumericData::getTm, QmsPointWeekNumericData::getEndv);
            else if (valueField == QmsPointValueFieldEnum.MAX_VALUE)//最大值
                wrapper.select(QmsPointWeekNumericData::getTm, QmsPointWeekNumericData::getMaxv);
            else if (valueField == QmsPointValueFieldEnum.MIN_VALUE)//最小值
                wrapper.select(QmsPointWeekNumericData::getTm, QmsPointWeekNumericData::getMinv);
            else//其他均查询value字段的值
                wrapper.select(QmsPointWeekNumericData::getTm, QmsPointWeekNumericData::getV);

            //查询条件
            //点号相等
            wrapper.eq(QmsPointWeekNumericData::getPointid, pointid);
            //判断时间,不小于指定时间点，≥time
            wrapper.ge(QmsPointWeekNumericData::getTm, time);
            //判断数据质量要求
            if (quality != QmsPointDataQualityEnum.UN_DEFINE)
                wrapper.ge(QmsPointWeekNumericData::getQuality, quality);
            //将查询指定字段数据值为null的排除在外
            if (valueField == QmsPointValueFieldEnum.BEGIN_VALUE)//时段初值
                wrapper.isNotNull(QmsPointWeekNumericData::getBeginv);
            else if (valueField == QmsPointValueFieldEnum.END_VALUE)//时段末值
                wrapper.isNotNull(QmsPointWeekNumericData::getEndv);
            else if (valueField == QmsPointValueFieldEnum.MAX_VALUE)//最大值
                wrapper.isNotNull(QmsPointWeekNumericData::getMaxv);
            else if (valueField == QmsPointValueFieldEnum.MIN_VALUE)//最小值
                wrapper.isNotNull(QmsPointWeekNumericData::getMinv);
            else//其他均查询value字段的值
                wrapper.isNotNull(QmsPointWeekNumericData::getV);

            //按时间Asc，限制1条
            wrapper.orderByAsc(QmsPointWeekNumericData::getTm);
            wrapper.last("limit 1");

            //查询数据
            QmsPointWeekNumericData en = repository.selectOne(wrapper);
            if (en != null) {
                Map<LocalDateTime, Double> result = new LinkedHashMap<>();

                if (valueField == QmsPointValueFieldEnum.BEGIN_VALUE)//时段初值
                    result.put(en.getTm(), en.getBeginv());
                else if (valueField == QmsPointValueFieldEnum.END_VALUE)//时段末值
                    result.put(en.getTm(), en.getEndv());
                else if (valueField == QmsPointValueFieldEnum.MAX_VALUE)//最大值
                    result.put(en.getTm(), en.getMaxv());
                else if (valueField == QmsPointValueFieldEnum.MIN_VALUE)//最小值
                    result.put(en.getTm(), en.getMinv());
                else//其他均查询value字段的值
                    result.put(en.getTm(), en.getV());

                return result;
            }
        }

        return null;
    }

    /**
     * 新增insert点号数据，不进行数据的任何验证和校验，要求受影响的数据行数必须为1
     *
     * @param data 点号数据
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2025/10/2
     */
    public String add(QmsPointWeekNumericData data) {
        try {
            int affectRows = repository.insert(data);
            if (affectRows != 0x1)
                return "新增周点号数据失败，受影响的数据行数为" + affectRows;

            return QCUnifyReturnValue.Success();
        } catch (Exception ex) {
            return "新增周点号数据异常，" + ex.getMessage();
        }
    }

    /**
     * 修改update点号数据，不进行数据的任何验证和校验，要求受影响的数据行数必须为1
     *
     * @param data 点号数据
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2025/10/2
     */
    public String update(QmsPointWeekNumericData data) {
        LambdaUpdateWrapper<QmsPointWeekNumericData> wrapper = new LambdaUpdateWrapper<>();
        //更新字段：数值、特征值列、数据质量、更新时间
        wrapper.set(QmsPointWeekNumericData::getV, data.getV());
        wrapper.set(QmsPointWeekNumericData::getBeginv, data.getBeginv());
        wrapper.set(QmsPointWeekNumericData::getEndv, data.getEndv());
        wrapper.set(QmsPointWeekNumericData::getMaxv, data.getMaxv());
        wrapper.set(QmsPointWeekNumericData::getMaxtm, data.getMaxtm());
        wrapper.set(QmsPointWeekNumericData::getMinv, data.getMinv());
        wrapper.set(QmsPointWeekNumericData::getMintm, data.getMintm());
        wrapper.set(QmsPointWeekNumericData::getQuality, data.getQuality());
        wrapper.set(QmsPointWeekNumericData::getUptm, data.getUptm());
        //条件：点号和时间相同
        wrapper.eq(QmsPointWeekNumericData::getPointid, data.getPointid());
        wrapper.eq(QmsPointWeekNumericData::getTm, data.getTm());

        try {
            int affectRows = repository.update(data, wrapper);
            if (affectRows != 0x1)
                return "修改周点号数据失败，受影响的数据行数为" + affectRows;

            return QCUnifyReturnValue.Success();
        } catch (Exception ex) {
            return "修改周点号数据异常，" + ex.getMessage();
        }
    }

    /**
     * 设置数据质量标记，返回实际修改后的点号数据集合
     * 设置数据质量标记只能是人工操作，并且只能设置为删除、错误或人工数据（正确）3种质量中的一种
     *
     * @param pointid   点号
     * @param beginTime 数据起始时标
     * @param endTime   数据截止时标
     * @param quality   设置的数据质量标记
     * @param uptm      指定修改数据质量标记的时间，方便修改后获取修改后的数据信息
     * @return java.util.List<qc.module.qms.entity.QmsPointWeekNumericData>
     * @author QuCheng Tech
     * @since 2025/10/10
     */
    public List<QmsPointWeekNumericData> setQuality(String pointid, LocalDateTime beginTime, LocalDateTime endTime,
                                                    QmsPointDataQualityEnum quality, LocalDateTime uptm) throws QCPromptException {
        if (StringUtils.isBlank(pointid))
            throw new QCPromptException("点号编码不能为空");
        if (beginTime == null)
            throw new QCPromptException("数据起始时间不能为空");
        if (endTime == null)
            throw new QCPromptException("数据截止时间不能为空");
        if (beginTime.isAfter(endTime))
            throw new QCPromptException("数据起始时间不能大于截止时间");
        if (quality == null)
            throw new QCPromptException("要设置的数据质量不能为空");
        //要设置的数据质量只能为以下几种：根据要设置的数据质量设置不同的修改条件
        //DELETE：删除数据；修改使用的过滤条件：数据质量＞DELETE(1, "已删除")
        //ERROR：人工判断数据为错误数据；修改使用的过滤条件：数据质量＞ERROR(2, "错误数据")
        //MANUAL：人工判断数据为正确数据；修改使用的过滤条件：数据质量＜MANUAL(9, "人工数据")
        if (quality != QmsPointDataQualityEnum.DELETE || quality != QmsPointDataQualityEnum.ERROR || quality != QmsPointDataQualityEnum.MANUAL)
            throw new QCPromptException("要设置的数据质量不能为" + quality);

        //如果传入的uptm为null，自动设置为now
        if (uptm == null)
            uptm = LocalDateTimeUtil.getNow();

        LambdaUpdateWrapper<QmsPointWeekNumericData> updateWrapper = new LambdaUpdateWrapper<>();
        //更新字段：数据质量、更新时间
        updateWrapper.set(QmsPointWeekNumericData::getQuality, quality);
        updateWrapper.set(QmsPointWeekNumericData::getUptm, LocalDateTimeUtil.getNow());
        //条件：点号相同、时间段、数据质量
        updateWrapper.eq(QmsPointWeekNumericData::getPointid, pointid);
        //数据时标判断是一个时间点还是一段时间，分开设置数据时标的条件
        if (endTime.isAfter(beginTime)) {
            updateWrapper.ge(QmsPointWeekNumericData::getTm, beginTime);
            updateWrapper.le(QmsPointWeekNumericData::getTm, endTime);
        } else {
            updateWrapper.eq(QmsPointWeekNumericData::getTm, beginTime);
        }
        if (quality == QmsPointDataQualityEnum.DELETE || quality == QmsPointDataQualityEnum.ERROR)
            updateWrapper.gt(QmsPointWeekNumericData::getQuality, quality);
        else
            updateWrapper.lt(QmsPointWeekNumericData::getQuality, quality);

        try {
            int affectCount = repository.update(null, updateWrapper);
            if (affectCount > 0x0) {
                LambdaQueryWrapper<QmsPointWeekNumericData> queryWrapper = new LambdaQueryWrapper<>();
                //查询所有字段
                //条件：点号相同、时间段、数据质量、更新时间
                queryWrapper.eq(QmsPointWeekNumericData::getPointid, pointid);
                //数据时标判断是一个时间点还是一段时间，分开设置数据时标的条件
                if (endTime.isAfter(beginTime)) {
                    queryWrapper.ge(QmsPointWeekNumericData::getTm, beginTime);
                    queryWrapper.le(QmsPointWeekNumericData::getTm, endTime);
                } else {
                    queryWrapper.eq(QmsPointWeekNumericData::getTm, beginTime);
                }
                queryWrapper.eq(QmsPointWeekNumericData::getQuality, quality);
                queryWrapper.eq(QmsPointWeekNumericData::getUptm, uptm);
                //排序，按数据时标asc
                queryWrapper.orderByAsc(QmsPointWeekNumericData::getTm);

                return repository.selectList(queryWrapper);
            }
        } catch (Exception ex) {
            throw new QCPromptException("修改周点号数据质量异常，" + ex.getMessage());
        }

        return null;
    }

    /**
     * 获取设置数据质量标记为正确数据（人工数据）会产生影响的点号数据集合
     * 用于人工在设置点号数据为有效数据（正确数据）前获取会影响的点号数据集合用于进行数据值有效性判断及防误处理
     *
     * @param pointid   点号
     * @param beginTime 数据起始时标
     * @param endTime   数据截止时标
     * @return java.util.List<qc.module.qms.entity.QmsPointWeekNumericData>
     * @author QuCheng Tech
     * @since 2025/10/25
     */
    public List<QmsPointWeekNumericData> getManualSetQualityRightAffectDatas(String pointid, LocalDateTime beginTime, LocalDateTime endTime) {
        //基本输入错误时不进行数据查询
        if (StringUtils.isNotBlank(pointid) && beginTime != null && endTime != null && beginTime.isAfter(endTime) == false) {
            LambdaQueryWrapper<QmsPointWeekNumericData> queryWrapper = new LambdaQueryWrapper<>();
            //条件：点号相同、时间段、数据质量
            queryWrapper.eq(QmsPointWeekNumericData::getPointid, pointid);
            //数据时标判断是一个时间点还是一段时间，分开设置数据时标的条件
            if (endTime.isAfter(beginTime)) {
                queryWrapper.ge(QmsPointWeekNumericData::getTm, beginTime);
                queryWrapper.le(QmsPointWeekNumericData::getTm, endTime);
            } else {
                queryWrapper.eq(QmsPointWeekNumericData::getTm, beginTime);
            }
            //固定是人工设置数据为正确数据，设置后的数据质量为人工数据
            //MANUAL：人工判断数据为正确数据；修改使用的过滤条件：数据质量＜MANUAL(9, "人工数据")
            queryWrapper.lt(QmsPointWeekNumericData::getQuality, QmsPointDataQualityEnum.MANUAL);

            return repository.selectList(queryWrapper);
        }

        return null;
    }
}

